package com.atguigu.tingshu.common.config.pool;

import jakarta.annotation.PostConstruct;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/*
    单例模式
 */
@Configuration
@ConfigurationProperties(prefix = "tingshu.threadpool")
@Data
public class ThreadPoolConfig {
    private Integer coreSize;
    private Integer maxSize;
    private Long timeout;
    private Integer queueLength;

    private static Integer CORE_SIZE;
    private static Integer MAX_SIZE;
    private static Long TIMEOUT;
    private static Integer QUEUE_LENGTH;
    // jdk原生注解： 标注的方法必须是public 没有参数没有返回值的，会在构造器执行以后执行
    @PostConstruct
    public void init(){
        CORE_SIZE = this.coreSize;
        MAX_SIZE = this.maxSize;
        TIMEOUT = this.timeout;
        QUEUE_LENGTH = this.queueLength;
    }

    private volatile static ThreadPoolExecutor executor;
    /*
        bean的初始化过程：
            1、加载类： 静态属性也会加载  默认为null
            2、构造器： 成员属性值 默认为null
            3、组件类注解标注的类：
                @Configuration
                @ConfigurationProperties(prefix = "tingshu.threadpool")
                springioc容器 会根据prefix加载配置文件中的 配置设置给对象的成员属性
                设置属性值以后对象初始化成功
            4、生命周期方法：
                  @PostConstruct 标注的成员方法： 会在构造器调用之后执行
                    组件类 构造器只会在容器初始化对象时调用
                     @PostConstruct注解标注的成员方法 就由容器中的对象来调用

                 将容器设置的成员属性值 获取 设置给类的静态属性
            5、项目只要启动成功：
                静态属性一定会初始化成功
                在整个项目任何地方 获取类的静态属性 都可以直接使用
     */
    public static ThreadPoolExecutor getExecutor(){
        if(null != executor){
            return executor;
        }
        synchronized (ThreadPoolConfig.class){
            if(null != executor){
                return executor;
            }
            executor = new ThreadPoolExecutor(CORE_SIZE,
                    MAX_SIZE ,TIMEOUT , TimeUnit.SECONDS , new ArrayBlockingQueue<>(QUEUE_LENGTH),
                    Executors.defaultThreadFactory() , new ThreadPoolExecutor.AbortPolicy()
                    );
            return executor;
        }
    }

}
